package cn.sangyy.car.service.impl;

import cn.sangyy.basic.config.HighlightResultMapper;
import cn.sangyy.basic.utils.PageList;
import cn.sangyy.basic.utils.SearchUtil;
import cn.sangyy.car.doc.CarDoc;
import cn.sangyy.car.query.CarSearchQuery;
import cn.sangyy.car.service.ICarSearchService;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.BucketOrder;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @author SangYY
 * @date: 2023/05/30/10:06
 */
@Service
public class CarSearchServiceImpl implements ICarSearchService {

//    @Autowired
//    private CarRepository carRepository;
    @Autowired
    private HighlightResultMapper highlightResultMapper;
    @Autowired
    private ElasticsearchRestTemplate restTemplate;

    @Override
    public PageList<CarDoc> search(CarSearchQuery query) {
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        BoolQueryBuilder boolQuery = new BoolQueryBuilder();
        //关键字查询
        String keyword = query.getKeyword();
        if(StringUtils.isNotBlank(keyword)){
            boolQuery.must(QueryBuilders.multiMatchQuery(keyword.trim(),"title","shopName","typeName","carInfo"));
        }
        //其余条件查询
        buildBasicQuery(query, builder, boolQuery);
        //排序
        String sortType = query.getSortType();
        String sortField = query.getSortField();
        sortField = sortField == null ? "costprice":sortField;
        if(StringUtils.isNotBlank(sortType)){
            if(sortType.equals("asc")){
                builder.withSort(SortBuilders.fieldSort(sortField).order(SortOrder.ASC));
            }else {
                builder.withSort(SortBuilders.fieldSort(sortField).order(SortOrder.DESC));
            }
        }
        //高亮
        setHighLight(builder);
        //聚合查询、typeName和typeId
        TermsAggregationBuilder aggregation = AggregationBuilders.terms("typeIdGroup").field("lastParentTypeId")
                .order(BucketOrder.count(false)).size(30)
                .subAggregation(AggregationBuilders.
                        terms("typeNameGroup").field("parentTypeName.keyword"));
        builder.addAggregation(aggregation);
        //分页
        Integer page = query.getPage(); //当前页
        Integer size = query.getRows(); //每页记录数
        builder.withPageable(PageRequest.of(page-1,size));
//        Page<CarDoc> pages = carRepository.search(builder.build());
        AggregatedPage<CarDoc> pages = restTemplate.queryForPage(builder.build(), CarDoc.class, highlightResultMapper);
        List<CarDoc> rows = pages.getContent();
        long totals = pages.getTotalElements();
        Aggregations aggregations = pages.getAggregations();
        Map<String, Object> map = SearchUtil.getMapByAgg(aggregations);
        return new PageList<>(totals,rows,map);
    }

    private void setHighLight(NativeSearchQueryBuilder builder) {
        HighlightBuilder.Field title = new HighlightBuilder.Field("title")
                .preTags("<font style='color:#e4393c;'><b>").postTags("</b></font>");
        HighlightBuilder.Field shopName = new HighlightBuilder.Field("shopName")
                .preTags("<font style='color:#e4393c;'><b>").postTags("</b></font>");
        HighlightBuilder.Field typeName = new HighlightBuilder.Field("typeName")
                .preTags("<font style='color:#e4393c;'><b>").postTags("</b></font>");
        HighlightBuilder.Field carInfo = new HighlightBuilder.Field("carInfo")
                .preTags("<font style='color:#e4393c;'><b>").postTags("</b></font>");
        HighlightBuilder.Field[] fields = {title,shopName,typeName,carInfo};
        builder.withHighlightFields(fields);
    }

    private void buildBasicQuery(CarSearchQuery query, NativeSearchQueryBuilder builder, BoolQueryBuilder boolQuery) {
        Long typeId = query.getTypeId();
        String typeName = query.getTypeName();
        Integer carAge = query.getCarAge();
        Integer carAgeType = query.getCarAgeType();
        Double maxPrice = query.getMaxPrice();
        Double minPrice = query.getMinPrice();
        Integer mileage = query.getMileage();
        Integer mileageType = query.getMileageType();
        Integer costeffective = query.getCosteffective();
        Integer quasinewcar = query.getQuasinewcar();
        Integer rushsale = query.getRushsale();
        Integer transitivecountry = query.getTransitivecountry();
        Long lastParentTypeId = query.getLastParentTypeId();
        if(Objects.nonNull(lastParentTypeId)){
            boolQuery.filter(QueryBuilders.termQuery("lastParentTypeId",lastParentTypeId));
        }
        if(Objects.nonNull(costeffective)){ //是否超值
            boolQuery.filter(QueryBuilders.termQuery("costeffective",costeffective));
        }
        if(Objects.nonNull(quasinewcar)){ //是否准新车
            boolQuery.filter(QueryBuilders.termQuery("quasinewcar",quasinewcar));
        }
        if(Objects.nonNull(rushsale)){ // 是否急售
            boolQuery.filter(QueryBuilders.termQuery("rushsale",rushsale));
        }
        if(Objects.nonNull(transitivecountry)){ //是否全国迁移
            boolQuery.filter(QueryBuilders.termQuery("transitivecountry",transitivecountry));
        }
        if(Objects.nonNull(typeId)){
            boolQuery.filter(QueryBuilders.termQuery("typeId",typeId));
        }
        if(StringUtils.isNotBlank(typeName)){
            boolQuery.filter(QueryBuilders.termQuery("typeName",typeName.trim()));
        }
        if(Objects.nonNull(carAge) && Objects.nonNull(carAgeType)){
            Date date = DateUtils.addYears(new Date(), -carAge);
            if(carAgeType == 1){
                boolQuery.filter(QueryBuilders.rangeQuery("registertime").lt(date));
            }else {
                boolQuery.filter(QueryBuilders.rangeQuery("registertime").gt(date));
            }
        }
        if(Objects.nonNull(maxPrice) && Objects.nonNull(minPrice)){
            boolQuery.filter(QueryBuilders.rangeQuery("costprice").gte(minPrice).lt(maxPrice));
        }
        if(Objects.nonNull(mileage)){
            if(mileageType == 1){
                boolQuery.filter(QueryBuilders.rangeQuery("mileage").gt(mileage));
            }else {
                boolQuery.filter(QueryBuilders.rangeQuery("mileage").lte(mileage));
            }
        }
        builder.withQuery(boolQuery);
    }
}
